home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
MISC
/
DTMFF110
/
SC_SB16.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-05
|
6KB
|
246 lines
/*
* Routines for sampling from a Soundblaster-16 sound card.
* These routines require the functions in sbio.c derived from
* Ethan Brodsky's Soundblaster-16 programming library .
* Copyright (C) 1997 Philip VanBaren & Emil Laurentiu
* Last modified: Wednesday, 06 August 1997
*/
#include "freq.h"
#ifdef SC_SB16
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mem.h>
#include <graphics.h>
#include "sb.h"
#include "sbio.h"
#include "extern.h"
/* Function prototypes */
int atox16( char *ptr );
void interrupt sb16_callback( void );
void init_sb16( char **environ );
void reset_sb16( void );
void halt_sb16( void );
void cleanup_sb16( void );
void recordblock_sb16( void far * buffer );
void set_mixer_sb16( int mix, int level );
int
atox16( char *ptr )
{
// Convert ascii hex values to integer
int v = 0;
while ( ( ( *ptr >= '0' ) && ( *ptr <= '9' ) ) || ( ( ( *ptr | 0x20 ) >= 'a' ) && ( ( *ptr | 0x20 ) <= 'f' ) ) )
{
v = v * 16;
if ( *ptr <= '9' )
v = v + *ptr - '0';
else
v = v + ( *ptr | 0x20 ) - 'a' + 10;
ptr++;
}
return v;
}
#define is_blaster(var) ((((var)[0]=='B')||((var)[0]=='b')) && \
(((var)[1]=='L')||((var)[1]=='l')) && \
(((var)[2]=='A')||((var)[2]=='a')) && \
(((var)[3]=='S')||((var)[3]=='s')) && \
(((var)[4]=='T')||((var)[4]=='t')) && \
(((var)[5]=='E')||((var)[5]=='e')) && \
(((var)[6]=='R')||((var)[6]=='r')))
/* Turn off stack checking for this routine */
#pragma option -N-
void interrupt
sb16_callback( )
{
extern int poll16port, dma_maskport, dma_stopmask;
unsigned int far *s, far * d;
int i;
/*
* Callback function. This function is called every time a buffer has been
* filled. It copies the latest data, and sets a flag so the main loop
* recognises and processes the buffer.
*/
d = buffer[record_buffer];
s = dmaptr + (curblock * fftlen);
for ( i = 0; i < fftlen; i++ )
*d++ = *s++;
flag[record_buffer] = 1;
if ( ++record_buffer >= BUFFERS )
record_buffer = 0;
curblock = !curblock; /* Toggle active block flag */
/* If we hit the end of the queued buffers, stop recording */
if ( record_buffer == queue_buffer )
{
write_dsp( 0xD5 ); /* Stop digitized sound xfer */
outportb( dma_maskport, dma_stopmask ); /* Mask DMA channel */
sb16dmarunning = 0;
}
/* Acknowledge the interrupt */
inportb( poll16port );
outportb( 0x20, 0x20 );
outportb( 0xA0, 0x20 );
}
/* Restore stack checking to the command-line specified state */
#pragma option -N.
void
init_sb16( char **environ )
{
int i;
// Scan the environment variables for BLASTER=Axxx Ix Dx
for ( i = 0; environ[i] != NULL; i++ )
{
if ( is_blaster( environ[i] ) )
{
int j;
DOUT( "SB16: Found the BLASTER environment variable:" );
DOUT( environ[i] );
for ( j = 8; environ[i][j] != 0; j++ )
{
if ( ( environ[i][j] == 'A' ) || ( environ[i][j] == 'a' ) )
{
DOUT( "SB16: Axxx found" );
sb_addr = atox16( &environ[i][j + 1] );
}
if ( ( environ[i][j] == 'H' ) || ( environ[i][j] == 'h' ) )
{
DOUT( "SB16: Hx found" );
sb_dma = atoi( &environ[i][j + 1] );
}
if ( ( environ[i][j] == 'I' ) || ( environ[i][j] == 'i' ) )
{
DOUT( "SB16: Ix found" );
sb_irq = atoi( &environ[i][j + 1] );
}
// Skip to the next parameter
while ( ( environ[i][j] != ' ' ) && ( environ[i][j + 1] != 0 ) )
j++;
}
break;
}
}
#ifdef DEBUG_OUTPUT
{
char message[100];
sprintf( message, "SB16: Address=0x%03x, DMA=%d, IRQ=%d", sb_addr, sb_dma, sb_irq );
DOUT( message );
}
#endif
/* Set up the pointers to the recording routines */
reset_soundcard = reset_sb16;
halt_soundcard = halt_sb16;
cleanup_soundcard = cleanup_sb16;
recordblock = recordblock_sb16;
set_mixer = set_mixer_sb16;
sample_size = 16;
mixers = 1;
DOUT( "SB16: Initializing the card" );
if ( !init_sb( sb_addr, sb_irq, sb_dma, input, MAX_LEN ) )
{
closegraph( );
puts( "Unable to initialize the Soundblaster16 card, aborting..." );
exit( 1 );
}
DOUT( "SB16: Reading initial mixer settings" );
mic_level = get_mic_level( );
ext_level = get_line_level( );
int_level = get_cd_level( );
DOUT( "SB16: Set Master volume & FM volume to maximum" );
set_master_level( 0x0f );
set_fm_level( 0x0f );
}
void
reset_sb16( void )
{
int i;
/* Round sampling rate to a valid value for the SB card */
i = floor( 1000000.0 / SampleRate + 0.5 );
if ( i < 1 )
i = 1;
SampleRate = floor( 1000000.0 / ( double ) i + 0.5 );
/* Reset the buffer pointers */
queue_buffer = 0; // Pointer to next buffer to be queued
record_buffer = 0; // Pointer to next buffer to be filled
process_buffer = 0; // Pointer to next buffer to be FFTed
for ( i = 0; i < BUFFERS; i++ )
flag[i] = 0;
/* This function starts the DMA process. */
DOUT( "SB16: Starting the recording process" );
recordblock_sb16( ( char far * ) buffer[queue_buffer] );
}
void
halt_sb16( void )
{
/*
* Shut down the DMA system.
*/
DOUT( "SB16: Stopping the sampling process" );
stopio( );
}
void
cleanup_sb16( void )
{
/*
* Shut down the DMA system and remove the interrupt handler.
*/
DOUT( "SB16: Stopping the sampling process and cleaning up" );
shutdown_sb( );
Sb_FM_Reset( );
}
void
recordblock_sb16( void far * buffer )
{
/* Start transferring data into the DMA buffer */
if ( ++queue_buffer >= BUFFERS )
queue_buffer = 0;
/* If the DMA has halted, restart it */
if ( !sb16dmarunning )
startio( ( unsigned int ) SampleRate, fftlen );
}
void
set_mixer_sb16( int mix, int level )
{
/*
* Set a mixer level on the PAS16 card
*/
if ( mix == MIXER_EXT )
{
DOUT( "SB16: Setting the line mixer level" );
set_line_level( level );
}
else if ( mix == MIXER_INT )
{
DOUT( "SB16: Setting the CD mixer level" );
set_cd_level( level );
}
else if ( mix == MIXER_MIC )
{
DOUT( "SB16: Setting the microphone mixer level" );
set_mic_level( level );
}
}
#endif